package com.hoas.quicklysdk.aliyun.sms;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.hoas.quicklysdk.aliyun.sms.configure.AliyunSmsProperties;
import com.hoas.quicksdk.api.ApiResult;
import com.hoas.quicksdk.api.sms.SmsClient;
import com.hoas.quicksdk.api.sms.SmsRsp;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class AliyunSmsClient implements SmsClient {

    private Logger logger = LoggerFactory.getLogger(AliyunSmsClient.class);

    public static final String FORMAT4 = "yyyy-MM-dd HH:mm:ss";

    private static Gson gson = new GsonBuilder().setDateFormat(FORMAT4).create();

    private static String LIMIT_CODE = "isv.BUSINESS_LIMIT_CONTROL";

    private AliyunSmsProperties properties;

    public AliyunSmsClient(AliyunSmsProperties properties) {
        this.properties = properties;
    }

    @Override
    public ApiResult<SmsRsp> sendSms(String[] phoneNumbers, String templateCode, Map<String, String> templateParam, String signName, String region) {

        if (phoneNumbers == null || phoneNumbers.length == 0) {
            return ApiResult.paramError("发送短信手机号不能为空");
        }

        if (phoneNumbers.length > 1000) {
            return ApiResult.paramError("发送短信手机号数量过多");
        }

        if ( StringUtils.isBlank(templateCode) ) {
            return ApiResult.paramError("模板编号缺失");

        }

        if (StringUtils.isBlank( signName )) {
            signName = properties.getSignName();
        }

        DefaultProfile profile = DefaultProfile.getProfile(properties.getRegionId(), properties.getAccessKeyId(), properties.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("PhoneNumbers", StringUtils.join(phoneNumbers, "."));
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("SignName", signName);

        if (StringUtils.isNotBlank( region )) {
            request.putQueryParameter("RegionId",  region);
        }

        if (templateParam != null && templateParam.size() > 0) {
            request.putQueryParameter("TemplateParam", gson.toJson( templateParam ));
        }

        try {
            logger.info("发送短信 templateNo={} \nparams={} \nphones={}", templateCode
                    , request.getSysQueryParameters().get("PhoneNumbers")
                    , request.getSysQueryParameters().get("TemplateParam"));
            CommonResponse response = client.getCommonResponse(request);
            logger.info("发送短信 templateNo={} httpStatus={} \nresp={}", templateCode, response.getHttpStatus(), response.getData());
            Map map = gson.fromJson(response.getData(), Map.class);

            String Code = MapUtils.getString(map, "Code");

            SmsRsp rsp = new SmsRsp();
            rsp.setBizId(MapUtils.getString(map, "BizId"));
            rsp.setRequestId(MapUtils.getString(map, "RequestId"));
            rsp.setResultCode(MapUtils.getString(map, "Code"));
            rsp.setResultMsg(MapUtils.getString(map, "Message"));


            if (LIMIT_CODE.equals( Code )) {
                return ApiResult.businessError( "短信发送过于频繁，请稍后再次尝试", null );
            }


            if ("OK".equals(Code)) {

                return ApiResult.success("短信发送成功", rsp );

            } else {

                return ApiResult.businessError( MapUtils.getString(map, "Message"), rsp );

            }


        } catch (ServerException e) {
            logger.error("发送短信 templateNo={} 发送异常", templateCode);
        } catch (ClientException e) {
            logger.error("发送短信 templateNo={} 发送异常", templateCode);
        }

        return ApiResult.error("短信发送失败");
    }

    @Override
    public ApiResult<SmsRsp> sendSms(String[] phoneNumbers, String templateCode, Map<String, String> templateParam) {
        return sendSms( phoneNumbers, templateCode, templateParam, null, null);
    }

    @Override
    public ApiResult<SmsRsp> sendSms(String phoneNumber, String templateCode, Map<String, String> templateParam) {
        return sendSms( new String[]{ phoneNumber }, templateCode, templateParam, null, null);
    }

    @Override
    public ApiResult<SmsRsp> sendBatchSms(String[] phoneNumbers, String templateCode, List<Map<String, String>> templateParams, String signName, String region) {

        if (phoneNumbers == null || phoneNumbers.length == 0) {
            return ApiResult.paramError("发送短信手机号不能为空");
        }

        if ( StringUtils.isBlank(templateCode) ) {
            return ApiResult.paramError("模板编号缺失");
        }

        if (StringUtils.isBlank( signName )) {
            signName = properties.getSignName();
        }

        DefaultProfile profile = DefaultProfile.getProfile(properties.getRegionId(), properties.getAccessKeyId(), properties.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendBatchSms");
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("PhoneNumberJson", gson.toJson(phoneNumbers));

        String[] signs = new String[phoneNumbers.length];
        for (int i = 0; i < signs.length; i++) {
            signs[i] = signName;
        }

        request.putQueryParameter("SignNameJson", gson.toJson(signs));

        if (templateParams != null && templateParams.size() > 0) {

            if (templateParams.size() != phoneNumbers.length) {
                return ApiResult.paramError("模板参数组个数与手机个数不一致");
            }

            request.putQueryParameter("TemplateParamJson", gson.toJson( templateParams ));
        }
        if (StringUtils.isNotBlank( region )) {
            request.putQueryParameter("RegionId",  region);
        }

        try {

            logger.info("发送短信 templateNo={} \nparams={} \nphones={}", templateCode
                    , request.getSysQueryParameters().get("PhoneNumberJson"));

            CommonResponse response = client.getCommonResponse(request);

            logger.info("发送短信 templateNo={} httpStatus={} \nresp={}", templateCode, response.getHttpStatus(), response.getData());
            Map map = gson.fromJson(response.getData(), Map.class);

            String Code = MapUtils.getString(map, "Code");

            SmsRsp rsp = new SmsRsp();
            rsp.setBizId(MapUtils.getString(map, "BizId"));
            rsp.setRequestId(MapUtils.getString(map, "RequestId"));
            rsp.setResultCode(MapUtils.getString(map, "Code"));
            rsp.setResultMsg(MapUtils.getString(map, "Message"));

            if (LIMIT_CODE.equals( Code )) {
                return ApiResult.businessError( "短信发送过于频繁，请稍后再次尝试", null );
            }


            if ("OK".equals(Code)) {

                return ApiResult.success("短信发送成功", rsp );

            } else {

                return ApiResult.businessError( MapUtils.getString(map, "Message"), rsp );

            }

        } catch (ServerException e) {
            logger.info("发送短信 templateNo={} 发送异常", templateCode);
        } catch (ClientException e) {
            logger.info("发送短信 templateNo={} 发送异常", templateCode);
        }

        return ApiResult.error("短信发送失败");

    }

    @Override
    public ApiResult<SmsRsp> sendBatchSms(String[] phoneNumbers, String templateCode, List<Map<String, String>> templateParams) {
        return sendBatchSms( phoneNumbers, templateCode, templateParams, null, null);
    }

}
